const webpack = require('webpack');
const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");//提取css到单独文件的插件
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');//压缩css插件
const TerserWebpackPlugin = require('terser-webpack-plugin');
const apiMocker = require('mocker-api');

console.log('当前环境:', process.env.NODE_ENV)

// 打包输出目录, 以及 devServer 的 contentBase
const outputDir = 'dist';

// 判断当前环境变量设置的是否为开发环境
const isDev = process.env.NODE_ENV === 'development'

const sourceMap = process.env.NODE_ENV !== 'production'

const minimizer = [];
if (!isDev) {
    minimizer.push(new TerserWebpackPlugin(), new OptimizeCssAssetsPlugin());
}

const plugins = [
    new CopyPlugin({
        // 这里表示, 执行打包或运行devServer时PROJECT_ROOT/public 目录下的所有内容, 会不经过打包, 直接复制到 PROJECT_ROOT/${outputDir}/public代指的目录, 可以通过url直接访问
        patterns: [{from: path.join(__dirname, 'public'), to: path.join(__dirname, `${outputDir}/public`)}],
    }),
    new HtmlWebpackPlugin({
        appMountId: 'app',
        template: path.join(__dirname, 'template.ejs'),
        filename: 'index.html'
    }),
    new CleanWebpackPlugin(),
    new MiniCssExtractPlugin({
        filename: isDev ? '[name].css' : "css/[name].[contenthash].css",
        chunkFilename: isDev ? '[id].css' : 'css/[id].[contenthash].css',
    })
];
if (process.env.ANALYZER === 'true') {
    plugins.push(
        new BundleAnalyzerPlugin({
            analyzerMode: 'static',
            openAnalyzer: false,
        })
    )
}


const config = {
    entry: [
        './src/index.tsx'
    ],
    output: {
        path: path.resolve(__dirname, outputDir),
        filename: 'js/[name].[contenthash].js',
        // TODO 如果是发布在非根目录, 导致加载js和css出现404, 可以将目录名称设置到 publicPath 解决该问题
        // publicPath:'/'
    },
    externals: {},
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                use: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    {
                        loader: 'css-loader',
                        options: {
                            importLoaders: 1,
                            sourceMap: sourceMap
                        }
                    },
                    'postcss-loader'
                ],
                exclude: /\.module\.css$/
            },
            {
                test: /\.ts(x)?$/,
                /*
                这里之所以要先使用ts-loader解析, 再使用babel-loader解析,是为了使用babel-loader的按需引入插件,来解决ant的样式按需引入问题,
                如果并未使用antd或并未采用按需引入方式, 那只要配置ts-loader即可. 除了从界面样式之外, 如何判断按需引入成功了呢? 打开web控制台的源代码标签页,
                如果对应站点下存在vendors.css, 且包含antd样式, 那说明按需引入成功了
                 */
                use: ['babel-loader', 'ts-loader'],
                exclude: /\.d\.ts/
            },
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    {
                        loader: 'css-loader',
                        options: {
                            importLoaders: 1,
                            modules: true,
                            sourceMap: sourceMap
                        }
                    },
                    'postcss-loader'
                ],
                include: /\.module\.css$/,
                exclude: /node_modules/,
            },
            {
                test: /\.scss$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'sass-loader'
                ],
                exclude: /\.module\.scss$/
            },
            {
                test: /\.scss$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    {
                        loader: 'css-loader',
                        options: {
                            sourceMap: sourceMap,
                            importLoaders: 1,
                            modules: {
                                localIdentName: '[local]_[hash:base64:5]'
                            }
                        }
                    },
                    {
                        loader: 'sass-loader'
                    }
                ],
                include: /\.module\.scss$/,
                exclude: /node_modules/,
            },
            {
                test: /\.less$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    {
                        loader: 'less-loader',
                        options: {
                            lessOptions: {
                                javascriptEnabled: true,
                                // 在此处进行antd的主题定制
                                modifyVars: {
                                    'primary-color': '#1DA57A'
                                }
                            }
                        }
                    }
                ],
                exclude: /\.module\.less$/
            },
            {
                test: /\.less$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    {
                        loader: 'css-loader',
                        options: {
                            sourceMap: sourceMap,
                            importLoaders: 1,
                            modules: {
                                localIdentName: '[local]_[hash:base64:5]'
                            }
                        }
                    },
                    {
                        loader: 'less-loader',
                        options: {
                            lessOptions: {
                                javascriptEnabled: true
                            }
                        }
                    }
                ],
                include: /\.module\.less$/,
                exclude: /node_modules/,
            },
            {
                test: /\.png$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            mimetype: 'image/png'
                        }
                    }
                ]
            },
            {
                test: /\.(jpg|jpeg)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            mimetype: 'image/jpg'
                        }
                    }
                ]
            }
        ]
    },
    resolve: {
        extensions: [
            '.js',
            '.jsx',
            '.tsx',
            '.ts'
        ],
        alias: {
            '@': path.resolve(__dirname, 'src'),
            '@images': path.resolve(__dirname, 'src/asserts/images')
        }
    },
    devServer: {
        // contentBase 应该与output.path一致
        contentBase: `./${outputDir}`,
        open: true,
        // 代理方式访问后台接口, 则请求以 /webapi/xxx 开头, 这个proxy不要和before.apiMocker.proxy一致,否则会有问题
        proxy: {
            '/webapi': {
                target: 'http://localhost:8086/wwgl',
                pathRewrite: {'^/webapi': ''},
            },
        },
        // 期望使用mock接口,则将请求以 /api/xxx 开头
        before(app) {
            apiMocker(app, path.resolve('./mock/index.js'), {
                proxy: {
                    '/mockapi/(.*)': 'http://localhost:8081/admin'
                },
                changeHost: true,
            })
        },
    },
    plugins: plugins,
    optimization: {
        minimize: true,
        minimizer: minimizer,
        runtimeChunk: 'single',
        splitChunks: {
            chunks: 'all',
            automaticNameDelimiter: '-',// 文件名分隔符
            minChunks: 1, // 被提取的一个模块至少需要在几个 chunk 中被引用，这个值越大，抽取出来的文件就越小
            maxInitialRequests: 10, // 入口点的最大并行请求数
            maxAsyncRequests: 10,// 按需加载时的最大并行请求数，为 1 的时候就不会抽取公共 chunk 了
            cacheGroups: {
                vendor: {
                    test: /[\\/]node_modules[\\/]/,
                    name: 'vendors',
                    chunks: 'all'
                }
            }
        }
    }
};

module.exports = (env, argv) => {
    return config;
};
